﻿#pragma once

class Rng
{
# pragma region 默认实例

private:
	static Rng* m_Default;
public:
	static Rng* rng();

# pragma  endregion

# pragma region 线性同余参数

	//线性同余随机数生成算法
	private :
		const int PrimeA = 214013;
	const int PrimeB = 2531011;
# pragma endregion

	const float Mask15Bit_1 = 1.0f / 0x7fff;
	const int Mask15Bit = 0x7fff;

public:
	int Seed = 0;

	float Random()
	{
		auto val = ((((Seed = Seed * PrimeA + PrimeB) >> 16) & Mask15Bit) - 1) * Mask15Bit_1;
		if (val < 0) val = 0;
		return (val > 0.99999f ? 0.99999f : val);
	}
	
	float Range(float min, float max)
	{
		return min + Random() * (max - min);
	}
	
	int Range(int min, int max)
	{
		return (int)(min + Random() * (max - min));
	}
	
	float Range(float max)
	{
		return Range(0.0f, max);
	}
	
	int Range(int max)
	{
		return Range(0, max);
	}

	/// <summary>
	/// 包含边界；
	/// </summary>
	int Inclusive(int minOrMax, int max = 0x80000000)
	{
		if (max == 0x80000000)
		{
			max = minOrMax;
			minOrMax = 0;
		}

		max++;
		return (int)(minOrMax + Random() * (max - minOrMax));
	}

	template<typename T>
	void Shuffle(TArray<T> items)
	{
		//随机交换
		int currentIndex;
		T tempValue;
		for (int i = items.Num() - 1; i >= 0; i--)
		{
			currentIndex = rng()->Range(i + 1);

			tempValue = items[currentIndex];
			items[currentIndex] = items[i];
			items[i] = tempValue;
		}
	}

	void SetTimeSeed()
	{
		// int mon = DateTime.Now.Month;
		// int day = DateTime.Now.Day;
		// int hor = DateTime.Now.Hour;
		// int min = DateTime.Now.Minute;
		// int sec = DateTime.Now.Second;
		// int seed = (int) GMath.HashInts(mon, day, hor, min, sec);
		// // Debug.Log("时间设置随机种子：" + mon + "." + day + "." + hor + "." + min + "." + sec + "." + seed);
		// m_Seed = seed;
		Seed = 1;
	}

	bool OneIn(int chance)
	{
		return Range(chance) == 0;
	}

	bool Percent(int chance)
	{
		return Range(100) < chance;
	}
	
};
